/*
 * =====================================================================================
 *
 *       Filename:  cl_signal_handler.hxx
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  03/27/2011 10:12:30 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Chen Ken (Ken), zlchen.ken@gmail.com
 *        Company:  EMC
 *
 * =====================================================================================
 */

#ifndef _CL_SIGNAL_HANDLER_HXX_
#define _CL_SIGNAL_HANDLER_HXX_

#include <signal.h>
#include <pthread.h>
#include <vector>
#include <map>
#include <memory>
#include "cl_callback.hxx"

namespace neo
{
class CLThread;
class CLLock;

typedef std::vector<int> CLSignalSet;

// CLSignalHandler should be a singleton
class CLSignalHandler
{
public:
  explicit CLSignalHandler(bool asyncMode = false);
  ~CLSignalHandler();
  bool installHandlerFor(int sigNum, const CLCallbackFunctor& cb);
  bool uninstallHandlerFor(int sigNum);

  // The signal handlers should already be installed 
  // before calling waitForSignal
  void waitForSignal(void);
  void dispatch(void);

	// For SIGSEGV, ABORT...
  static void dispatchForSpecial(int sigNum);

private:
	// typedefs
	typedef void (*SignalCallBack)(int, siginfo_t *, void *);
  typedef std::vector<CLCallbackFunctor> CallbackVec;
  typedef std::map<int,  CallbackVec> SignalHandlerMap;
  typedef std::map<int,  struct sigaction> SigactionMap;

private:
  void doDispatch(int sigNum);
  const CLSignalSet blockedSignals(void) const;
  static void doCallbacks(CallbackVec& callbacks);
  static bool installHandlerForSpecial(int sigNum, const CLCallbackFunctor& cb);
  static bool doInstallHandlerForSpecial(int sigNum);
  static bool uninstallHandlerForSpecial(int sigNum);
  static bool doUninstallHandlerForSpecial(int sigNum);

private:
  CLSignalHandler(const CLSignalHandler&);
  CLSignalHandler& operator=(const CLSignalHandler&);

private:
  bool m_asyncMode;
  SignalHandlerMap m_installedSignalHandlers;
  CLSignalSet m_blockedSignals;
  std::unique_ptr<CLLock> m_lock;
  std::unique_ptr<CLThread> m_thr;

private:
  static SigactionMap m_origSigactionForSpecial;
  static SignalHandlerMap m_signalHandlersForSpecial;
  static std::unique_ptr<CLLock> m_lockForSpecial;
};

/////
class CLBlockSignal
{
public:
	CLBlockSignal(const CLSignalSet& sigSet);
	~CLBlockSignal();

private:
	const CLSignalSet  m_sigSet;
};

} // neo

#endif //_CL_SIGNAL_HANDLER_HXX_

